package com.hyq.grid.algorithm;

import com.hyq.grid.common.File_operation;
import com.hyq.grid.common.tools;

import java.awt.*;
import java.awt.geom.Point2D;
import java.io.IOException;
import java.util.*;
import java.util.List;


public class gmsh {

    private List<Map<String, Double>> border;
    private List<Point2D.Double> borderPoints;
    private Double distance;

    private String gmshPath = "D:\\gmsh-4.6.0-Windows64\\";
    public StringBuilder strPrintBuilder;

    public gmsh(Double distance) {
        this.distance = distance;
    }

    public gmsh(List<Map> border, Double distance) {
        this.distance = distance;
        borderPoints = new ArrayList<>();

        for (int i = 0; i < border.size(); i++) {
            borderPoints.add(new Point2D.Double(Double.parseDouble((border.get(i).get("X")).toString()), Double.parseDouble((border.get(i).get("Y")).toString())));
//            borderPoints.add(new Point2D.Double(Double.parseDouble((border.get(i).get(0)).toString()), Double.parseDouble((border.get(i).get(1)).toString())));
        }
        strPrintBuilder = new StringBuilder("******OpenMesh1.0******\n");
    }

    public gmsh(List<Map<String, Double>> border) {
        this.border = border;
        this.distance = border.get(border.size() - 1).get("Distance");
        borderPoints = new ArrayList<>();
        for (int i = 0; i < border.size() - 1; i++) {
            borderPoints.add(new Point2D.Double(border.get(i).get("X"), border.get(i).get("Y")));
        }
    }

    public List<Map> del2d() throws Exception {
        createGeoFile(0);
//                调用gmsh 生成网格

        String command = "cmd /C " + gmshPath + "gmsh.exe temp.geo -2 -algo \" " + "del2d" + "\" -o temp.dat";
        Process p = Runtime.getRuntime().exec(command);
        p.waitFor();
        Map tempmap = File_operation.ReadFile("D:\\gmsh-4.6.0-Windows64\\temp.dat");
        List<Double[]> node = (List<Double[]>) tempmap.get("node");
        List<Integer[]> element = (List<Integer[]>) tempmap.get("element");
        List<Map> delatri = new ArrayList<>();
        for (int i = 0; i < element.size(); i++) {
            Map<String, Object> tempMap = new HashMap<String, Object>();
            double[] xout = new double[3];
            double[] yout = new double[3];
            xout[0] = node.get(element.get(i)[0] - 1)[0];
            xout[1] = node.get(element.get(i)[1] - 1)[0];
            xout[2] = node.get(element.get(i)[2] - 1)[0];

            yout[0] = node.get(element.get(i)[0] - 1)[1];
            yout[1] = node.get(element.get(i)[1] - 1)[1];
            yout[2] = node.get(element.get(i)[2] - 1)[1];


            tempMap.put("X", xout);
            tempMap.put("Y", yout);

            delatri.add(tempMap);

        }
        return delatri;
    }

    public Map<String, Object> quadsbackup() throws Exception {
        createGeoFile(1);
//                调用gmsh 生成网格
//        String command = "cmd /C cd E:\\网格研究\\gmsh-4.6.0-Windows64\\ & gmsh.exe temp.geo -2 -algo \"delquad\" -o temp.dat";
        String command = "cmd /C " + gmshPath + "gmsh.exe " + gmshPath + "temp.geo -2 -algo \"" + "delquad" + "\" -o " + gmshPath + "temp.dat";
        Process p = Runtime.getRuntime().exec(command);
        p.waitFor();
        Map tempmap = File_operation.ReadFile(gmshPath + "temp.dat");
        List<Double[]> node = (List<Double[]>) tempmap.get("node");
        List<Integer[]> element = (List<Integer[]>) tempmap.get("element");
        List<Map> delatri = new ArrayList<>();
        for (int i = 0; i < element.size(); i++) {
            if (element.get(i).length < 4) continue;
            Map<String, Object> tempMap = new HashMap<String, Object>();

            double[] xout = new double[4];
            double[] yout = new double[4];
            xout[0] = node.get(element.get(i)[0] - 1)[0];
            xout[1] = node.get(element.get(i)[1] - 1)[0];
            xout[2] = node.get(element.get(i)[2] - 1)[0];
            xout[3] = node.get(element.get(i)[3] - 1)[0];

            yout[0] = node.get(element.get(i)[0] - 1)[1];
            yout[1] = node.get(element.get(i)[1] - 1)[1];
            yout[2] = node.get(element.get(i)[2] - 1)[1];
            yout[3] = node.get(element.get(i)[3] - 1)[1];

            tempMap.put("X", xout);
            tempMap.put("Y", yout);

            delatri.add(tempMap);

        }
        Map<String, Object> returndata = new HashMap<>();
        returndata.put("node", node);
        returndata.put("element", delatri);
        return returndata;
    }

    public Map<String, Object> getquads() throws Exception {
        createGeoFile(1);
//                调用gmsh 生成网格
//        String command = "cmd /C cd E:\\网格研究\\gmsh-4.6.0-Windows64\\ & gmsh.exe temp.geo -2 -algo \"delquad\" -o temp.dat";
        String command = "cmd /C " + gmshPath + "gmsh.exe " + gmshPath + "temp.geo -2 -algo \"" + "delquad" + "\" -o " + gmshPath + "temp.dat";
        Process p = Runtime.getRuntime().exec(command);
        p.waitFor();
        Map tempmap = File_operation.ReadFile(gmshPath + "temp.dat");

//        存储网格信息
        List<Double[]> node = (List<Double[]>) tempmap.get("node");
        List<Integer[]> element = (List<Integer[]>) tempmap.get("element");
        List<Integer[]> elementIndex = new ArrayList<>();

//        背景网格信息
        Map boxIndex = creatBacGrid(distance);
        List<List> boxes = (List<List>) boxIndex.get("boxes");
        Point.Double startPoint = (Point2D.Double) boxIndex.get("startPoint");
        int xSize = (int) boxIndex.get("XLength");
        int ySize = (int) boxIndex.get("YLength");
        Double boxPrecision = (Double) boxIndex.get("precision");


        List<Map> delatri = new ArrayList<>();
        for (int i = 0; i < element.size(); i++) {
            if (element.get(i).length < 4) continue;
            Map<String, Object> tempMap = new HashMap<String, Object>();
            Integer[] tempElementIndex = new Integer[element.get(i).length];

            double[] xout = new double[element.get(i).length];
            double[] yout = new double[element.get(i).length];

            List<Double[]> tempElementCoordiantes = new ArrayList<>();
            for (int j = 0; j < element.get(i).length; j++) {

                xout[j] = node.get(element.get(i)[j] - 1)[0];
                yout[j] = node.get(element.get(i)[j] - 1)[1];

                tempElementCoordiantes.add(new Double[]{xout[j], yout[j]});

                tempElementIndex[j] = element.get(i)[j] - 1;
            }

//            装箱
            Double[] inCenter = tools.IncentreOfPolygon(tempElementCoordiantes);

            int xCount = (int) Math.floor((inCenter[0] - startPoint.x) / distance);
            int yCount = (int) Math.floor((inCenter[1] - startPoint.y) / distance);

            List<Integer> surroundboxes = tools.GetBoxIndex(xout, yout, startPoint, boxPrecision, xSize, ySize, new int[]{xCount, yCount});

            for (Integer currentboxes : surroundboxes) {
                List<Integer> curcontain = (List<Integer>) boxes.get(currentboxes);
                curcontain.add(i);
            }

            tempMap.put("X", xout);
            tempMap.put("Y", yout);

            delatri.add(tempMap);
            elementIndex.add(tempElementIndex);

        }

//        生成邻接表
        List<List> neighborList = tools.CreatNeighborList(node, elementIndex, boxIndex);

        Map<String, Object> returndata = new HashMap<>();
        returndata.put("node", node);
        returndata.put("element", delatri);
        returndata.put("elementIndex", elementIndex);
        returndata.put("boxIndex", boxIndex);
        returndata.put("neighbor", neighborList);
        return returndata;
    }

    public Map<String, Object> algo(String currentalgo) throws Exception {
//        ogr.RegisterAll();

        createGeoFile(0);
//                调用gmsh 生成网格

//        String command = "cmd /C cd D:\\gmsh-4.6.0-Windows64\\ && gmsh.exe temp.geo -2 -algo \"" + currentalgo + "\" -o temp.dat";
        String command = "cmd /C " + gmshPath + "gmsh.exe " + gmshPath + "temp.geo -2 -algo \"" + currentalgo + "\" -o " + gmshPath + "temp.dat";
        Process p = Runtime.getRuntime().exec(command);
        p.waitFor();
        Map tempmap = File_operation.ReadFile("D:\\gmsh-4.6.0-Windows64\\temp.dat");
        List<Double[]> node = (List<Double[]>) tempmap.get("node");//节点
        List<Integer[]> element = (List<Integer[]>) tempmap.get("element");//单元
        List<Map> neighbor = new ArrayList<>();//邻界关系
        List<Map> delatri = new ArrayList<>();
        List<Integer[]> elementIndex = new ArrayList<>();
        for (int i = 0; i < element.size(); i++) {
            Map<String, Object> tempMap = new HashMap<String, Object>();
            Map<String, Object> neighborMap = new HashMap<>();
            Integer[] tempelementIndex = new Integer[element.get(i).length];

            double[] xout = new double[element.get(i).length];
            double[] yout = new double[element.get(i).length];

            for (int j = 0; j < element.get(i).length; j++) {

                tempelementIndex[j] = element.get(i)[j] - 1; //存储网格单元点序号
//                存储网格单元坐标
                xout[j] = node.get(element.get(i)[j] - 1)[0];
                yout[j] = node.get(element.get(i)[j] - 1)[1];
            }


            tempMap.put("X", xout);
            tempMap.put("Y", yout);

            neighborMap.put("elementID", i);
            Integer[] a = element.get(i);
            List<Integer> neighborList = new ArrayList<>();
            for (int j = 0; j < element.size(); j++) {
                if (j == i) continue;
                Integer[] b = element.get(j);
                Set<Integer> tempsame = tools.getSameElement(a, b);
                if (tempsame.size() >= 2) {
                    neighborList.add(j);
                }

                if (neighborList.size() == 3) {
                    break;
                }

            }
            neighborMap.put("neighborID", neighborList);

            delatri.add(tempMap);
            neighbor.add(neighborMap);
            elementIndex.add(tempelementIndex);

        }
        Map<String, Object> returndata = new HashMap<>();
        returndata.put("node", node);
        returndata.put("element", delatri);
        returndata.put("neighbor", neighbor);
        returndata.put("elementIndex", elementIndex);
        return returndata;
    }

    //不带邻接关系的生成
    public Map<String, Object> algoNonei(String currentalgo) throws Exception {
//        ogr.RegisterAll();

        createGeoFile(0);
//                调用gmsh 生成网格

        String command = "cmd /C " + gmshPath + "gmsh.exe " + gmshPath + "temp.geo -2 -algo \"" + currentalgo + "\" -o " + gmshPath + "temp.dat";
        Process p = Runtime.getRuntime().exec(command);
        p.waitFor();
        Map tempmap = File_operation.ReadFile("D:\\gmsh-4.6.0-Windows64\\temp.dat");
        List<Double[]> node = (List<Double[]>) tempmap.get("node");//节点
        List<Integer[]> element = (List<Integer[]>) tempmap.get("element");//单元
//        List<Map> neighbor = new ArrayList<>();//邻界关系
        List<Map> delatri = new ArrayList<>();
        List<Integer[]> elementIndex = new ArrayList<>();
        for (int i = 0; i < element.size(); i++) {
            Map<String, Object> tempMap = new HashMap<String, Object>();
//            Map<String, Object> neighborMap = new HashMap<>();
            Integer[] tempelementIndex = new Integer[element.get(i).length];

            Double[] xout = new Double[element.get(i).length];
            Double[] yout = new Double[element.get(i).length];

            for (int j = 0; j < element.get(i).length; j++) {

                tempelementIndex[j] = element.get(i)[j] - 1; //存储网格单元点序号
//                存储网格单元坐标
                xout[j] = node.get(element.get(i)[j] - 1)[0];
                yout[j] = node.get(element.get(i)[j] - 1)[1];
            }


            tempMap.put("X", xout);
            tempMap.put("Y", yout);

//            neighborMap.put("elementID", i);
            Integer[] a = element.get(i);
            List<Integer> neighborList = new ArrayList<>();
//            for (int j = 0; j < element.size(); j++) {
//                if (j == i) continue;
//                Integer[] b = element.get(j);
//                Set<Integer> tempsame = tools.getSameElement(a, b);
//                if (tempsame.size() >= 2) {
//                    neighborList.add(j);
//                }
//            }
//            neighborMap.put("neighborID", neighborList);

            delatri.add(tempMap);
//            neighbor.add(neighborMap);
            elementIndex.add(tempelementIndex);

        }
        Map<String, Object> returndata = new HashMap<>();
        returndata.put("node", node);
        returndata.put("element", delatri);
//        returndata.put("neighbor", neighbor);
        returndata.put("elementIndex", elementIndex);
        return returndata;
    }

    //    优化邻接关系生成
    public Map<String, Object> algo1(String currentalgo) throws Exception {


        createGeoFile(0);
//        调用gmsh 生成网格
//        背景网格生成
        Map bacMap = creatBacGrid(distance);
        List<Map> bacGrid = (List<Map>) bacMap.get("bacGrid");
        Point.Double startPoint = ((List<Point2D.Double>) bacGrid.get(0).get("coordinates")).get(0);
        int xSize = (int) bacMap.get("XLength");


        String command = "cmd /C " + gmshPath + "gmsh.exe " + gmshPath + "temp.geo -2 -algo \"" + currentalgo + "\" -o " + gmshPath + "temp.dat";
        Process p = Runtime.getRuntime().exec(command);
        p.waitFor();
        Map tempmap = File_operation.ReadFile("D:\\gmsh-4.6.0-Windows64\\temp.dat");
        List<Double[]> node = (List<Double[]>) tempmap.get("node");//节点
        List<Integer[]> element = (List<Integer[]>) tempmap.get("element");//单元
        List<Map> neighbor = new ArrayList<>();//邻界关系
        List<Map> delatri = new ArrayList<>();
        List<Integer[]> elementIndex = new ArrayList<>();

        for (int i = 0; i < element.size(); i++) {
            Map<String, Object> tempMap = new HashMap<String, Object>();

            Integer[] tempelementIndex = new Integer[element.get(i).length];

            double[] xout = new double[element.get(i).length];
            double[] yout = new double[element.get(i).length];
            List<Double[]> currentTri = new ArrayList<>();
            for (int j = 0; j < element.get(i).length; j++) {

                tempelementIndex[j] = element.get(i)[j] - 1; //存储网格单元点序号
////                存储网格单元坐标
                xout[j] = node.get(element.get(i)[j] - 1)[0];
                yout[j] = node.get(element.get(i)[j] - 1)[1];

                currentTri.add(new Double[]{node.get(element.get(i)[j] - 1)[0], node.get(element.get(i)[j] - 1)[1]});

            }

            Double[] inCenter = tools.IncenterTriangle(currentTri);

            int xCount = (int) Math.floor((inCenter[0] - startPoint.x) / distance);
            int yCount = (int) Math.floor((inCenter[1] - startPoint.y) / distance);
            List<Integer> curcontain = (List<Integer>) bacGrid.get(yCount * xSize + xCount).get("contain");
            curcontain.add(i);
            tempMap.put("X", xout);
            tempMap.put("Y", yout);

            delatri.add(tempMap);
            elementIndex.add(tempelementIndex);
        }

        //生成邻接表
        for (int i = 0; i < element.size(); i++) {
            List<Double[]> currentTri = new ArrayList<>();
            for (int j = 0; j < element.get(i).length; j++) {
                currentTri.add(new Double[]{node.get(element.get(i)[j] - 1)[0], node.get(element.get(i)[j] - 1)[1]});
            }
            Double[] inCenter = tools.IncenterTriangle(currentTri);
            int xCount = (int) Math.floor((inCenter[0] - startPoint.x) / distance);
            int yCount = (int) Math.floor((inCenter[1] - startPoint.y) / distance);

            HashSet<Integer> neiTriOr = new HashSet<>();
            List<Integer> l1, l2, l3, l4, l5, l6, l7, l8, l9;
            l1 = (List<Integer>) bacGrid.get(yCount * xSize + xCount).get("contain");
            neiTriOr.addAll(l1);
            if ((yCount * xSize + xCount - 1) >= 0) {
                l2 = (List<Integer>) bacGrid.get(yCount * xSize + xCount - 1).get("contain");
                neiTriOr.addAll(l2);
            }
            if ((yCount * xSize + xCount + 1) < bacGrid.size()) {
                l3 = (List<Integer>) bacGrid.get(yCount * xSize + xCount + 1).get("contain");
                neiTriOr.addAll(l3);
            }
            if ((yCount * (xSize - 1) + xCount) >= 0) {
                l4 = (List<Integer>) bacGrid.get(yCount * (xSize - 1) + xCount).get("contain");
                neiTriOr.addAll(l4);
            }
            if ((yCount * (xSize + 1) + xCount) < bacGrid.size()) {
                l5 = (List<Integer>) bacGrid.get(yCount * (xSize + 1) + xCount).get("contain");
                neiTriOr.addAll(l5);
            }
            if ((yCount * (xSize - 1) + xCount - 1) >= 0) {
                l6 = (List<Integer>) bacGrid.get(yCount * (xSize - 1) + xCount - 1).get("contain");
                neiTriOr.addAll(l6);
            }
            if ((yCount * (xSize - 1) + xCount + 1) >= 0) {
                l7 = (List<Integer>) bacGrid.get(yCount * (xSize - 1) + xCount + 1).get("contain");
                neiTriOr.addAll(l7);
            }

            if ((yCount * (xSize + 1) + xCount - 1) < bacGrid.size() && (yCount * (xSize + 1) + xCount - 1) >= 0) {
                l8 = (List<Integer>) bacGrid.get(yCount * (xSize + 1) + xCount - 1).get("contain");
                neiTriOr.addAll(l8);
            }
            if ((yCount * (xSize + 1) + xCount + 1) < bacGrid.size()) {
                l9 = (List<Integer>) bacGrid.get(yCount * (xSize + 1) + xCount + 1).get("contain");
                neiTriOr.addAll(l9);
            }

            List<Integer> neiTri = new ArrayList<>();
            neiTri.addAll(neiTriOr);
            Map<String, Object> neighborMap = new HashMap<>();
            neighborMap.put("elementID", i);
            Integer[] a = element.get(i);
            List<Integer> neighborList = new ArrayList<>();
            for (int j = 0; j < neiTri.size(); j++) {
                Integer[] b = element.get(neiTri.get(j));
                Set<Integer> tempsame = tools.getSameElement(a, b);
                if (tempsame.size() >= 2) {
                    neighborList.add(neiTri.get(j));
                }

                if (neighborList.size() == 3) {
                    break;
                }

            }
            neighborMap.put("neighborID", neighborList);

            neighbor.add(neighborMap);

        }
        Map<String, Object> returndata = new HashMap<>();
        returndata.put("node", node);
        returndata.put("element", delatri);
        returndata.put("neighbor", neighbor);
        returndata.put("elementIndex", elementIndex);
        return returndata;
    }

    // 新版标准化存储结构
    public Map<String, Object> gmshAlgo(String currentalgo) throws Exception {


        createGeoFile(0);
//        调用gmsh 生成网格
//        背景网格生成

//        背景网格信息
        Map boxIndex = creatBacGrid(distance);
        List<List> boxes = (List<List>) boxIndex.get("boxes");
        Point.Double startPoint = (Point2D.Double) boxIndex.get("startPoint");
        int xSize = (int) boxIndex.get("XLength");
        int ySize = (int) boxIndex.get("YLength");
        Double boxPrecision = (Double) boxIndex.get("precision");

        String command = "cmd /C " + gmshPath + "gmsh.exe " + gmshPath + "temp.geo -2 -algo \"" + currentalgo + "\" -o " + gmshPath + "temp.dat";
        Process p = Runtime.getRuntime().exec(command);
        p.waitFor();
        Map tempmap = File_operation.ReadFile("D:\\gmsh-4.6.0-Windows64\\temp.dat");
        List<Double[]> node = (List<Double[]>) tempmap.get("node");//节点
        List<Integer[]> element = (List<Integer[]>) tempmap.get("element");//单元
        strPrintBuilder.append(tempmap.get("printNode"));


        List<Map> delatri = new ArrayList<>();
        List<Integer[]> elementIndex = new ArrayList<>();


//        装箱
        strPrintBuilder.append("******element******\n");
        for (int i = 0; i < element.size(); i++) {

            strPrintBuilder.append(i + " ");

            Map<String, Object> tempMap = new HashMap<String, Object>();

            Integer[] tempelementIndex = new Integer[element.get(i).length];

            double[] xout = new double[element.get(i).length];
            double[] yout = new double[element.get(i).length];
            List<Double[]> currentTri = new ArrayList<>();
            for (int j = 0; j < element.get(i).length; j++) {

                tempelementIndex[j] = element.get(i)[j] - 1; //存储网格单元点序号
                strPrintBuilder.append(element.get(i)[j] - 1 + " ");

////                存储网格单元坐标
                xout[j] = node.get(element.get(i)[j] - 1)[0];
                yout[j] = node.get(element.get(i)[j] - 1)[1];
                currentTri.add(new Double[]{node.get(element.get(i)[j] - 1)[0], node.get(element.get(i)[j] - 1)[1]});

            }
            strPrintBuilder.append("\n");

            Double[] inCenter = tools.IncenterTriangle(currentTri);

            int xCount = (int) Math.floor((inCenter[0] - startPoint.x) / distance);
            int yCount = (int) Math.floor((inCenter[1] - startPoint.y) / distance);

            List<Integer> surroundboxes = tools.GetBoxIndex(xout, yout, startPoint, boxPrecision, xSize, ySize, new int[]{xCount, yCount});

            for (Integer currentboxes : surroundboxes) {
                List<Integer> curcontain = (List<Integer>) boxes.get(currentboxes);
                curcontain.add(i);
            }


            tempMap.put("X", xout);
            tempMap.put("Y", yout);

            delatri.add(tempMap);
            elementIndex.add(tempelementIndex);
        }

        //生成邻接表
        strPrintBuilder.append("******neighbor******\n");
        List<List> neighborList = tools.CreatNeighborList(node, elementIndex, boxIndex);


        strPrintBuilder.append("******boxes******\n");
        for (int i = 0; i < boxes.size(); i++) {
            List<Integer> containbox = (List<Integer>) boxes.get(i);
//            if (containbox.size()> 0) {
            strPrintBuilder.append(i + " ");
            for (int j = 0; j < containbox.size(); j++) {
                strPrintBuilder.append(containbox.get(j) + " ");
            }
            strPrintBuilder.append("\n");
//            }
        }
        Map<String, Object> returndata = new HashMap<>();
        returndata.put("node", node);
        returndata.put("element", delatri);
        returndata.put("neighbor", neighborList);
        returndata.put("elementIndex", elementIndex);
        returndata.put("boxIndex", boxIndex);
        return returndata;
    }

    public Map<String, Object> gmsh3DAlgo(String currentalgo) throws Exception {


        create3DGeoFile();
//        调用gmsh 生成网格


        String command = "cmd /C " + gmshPath + "gmsh.exe " + gmshPath + "temp3D.geo -3 -algo \"" + currentalgo + "\" -o " + gmshPath + "temp3D.dat";
        Process p = Runtime.getRuntime().exec(command);
        p.waitFor();
        Map mydata = File_operation.parseDatFile("D:\\gmsh-4.6.0-Windows64\\temp3D.dat",3,4);
        System.out.println("算法: " + currentalgo +", 网格节点数: " +((List<Double[]>)mydata.get("node")).size() +  ", 网格单元数: " + ((List<Integer[]>)mydata.get("element")).size());
        return mydata;
    }

    public Map<String, Object> gmshAlgo1(String currentalgo) throws Exception {
        createGeoFile(0);
//        调用gmsh 生成网格
//        背景网格生成
        Map boxIndex = creatBacGridNew(distance);
        List<Map> boxes = (List<Map>) boxIndex.get("boxes");
        Point.Double startPoint = ((List<Point2D.Double>) boxes.get(0).get("coordinates")).get(0);
        int xSize = (int) boxIndex.get("xLength");


        String command = "cmd /C " + gmshPath + "gmsh.exe " + gmshPath + "temp.geo -2 -algo \"" + currentalgo + "\" -o " + gmshPath + "temp.dat";
        Process p = Runtime.getRuntime().exec(command);
        p.waitFor();
        Map tempmap = File_operation.ReadFileNew("D:\\gmsh-4.6.0-Windows64\\temp.dat");

        List<double[]> node = (List<double[]>) tempmap.get("node");//节点
        List<int[]> element = (List<int[]>) tempmap.get("element");//单元
        List<List<double[]>> elementCoordinates = new ArrayList<>();


        List<List<Integer>> neighbor = new ArrayList<>();//邻接关系
        strPrintBuilder.append(tempmap.get("printNode"));
//        装箱
        strPrintBuilder.append("******element******\n");

        for (int i = 0; i < element.size(); i++) {
            strPrintBuilder.append(i + " ");
            List<double[]> currentTri = new ArrayList<>();
            for (int j = 0; j < element.get(i).length; j++) {
                currentTri.add(new double[]{node.get(element.get(i)[j] - 1)[0], node.get(element.get(i)[j] - 1)[1]});
                strPrintBuilder.append(element.get(i)[j] - 1 + " ");

            }
            strPrintBuilder.append("\n");

            elementCoordinates.add(currentTri);

            double[] inCenter = tools.IncenterTriangleNew(currentTri);

            int xCount = (int) Math.floor((inCenter[0] - startPoint.x) / distance);
            int yCount = (int) Math.floor((inCenter[1] - startPoint.y) / distance);
            List<Integer> curcontain = (List<Integer>) boxes.get(yCount * xSize + xCount).get("contain");
            curcontain.add(i);
        }

        strPrintBuilder.append("******neighbor******\n");

        //生成邻接表
        for (int i = 0; i < element.size(); i++) {
            List<double[]> currentTri = new ArrayList<>();
            for (int j = 0; j < element.get(i).length; j++) {
                currentTri.add(new double[]{node.get(element.get(i)[j] - 1)[0], node.get(element.get(i)[j] - 1)[1]});
            }
            double[] inCenter = tools.IncenterTriangleNew(currentTri);
            int xCount = (int) Math.floor((inCenter[0] - startPoint.x) / distance);
            int yCount = (int) Math.floor((inCenter[1] - startPoint.y) / distance);

            HashSet<Integer> neiTriOr = new HashSet<>();
            List<Integer> l1, l2, l3, l4, l5, l6, l7, l8, l9;

            l1 = (List<Integer>) boxes.get(yCount * xSize + xCount).get("contain");
            neiTriOr.addAll(l1);
            if ((yCount * xSize + xCount - 1) >= 0) {
                l2 = (List<Integer>) boxes.get(yCount * xSize + xCount - 1).get("contain");
                neiTriOr.addAll(l2);
            }
            if ((yCount * xSize + xCount + 1) < boxes.size()) {
                l3 = (List<Integer>) boxes.get(yCount * xSize + xCount + 1).get("contain");
                neiTriOr.addAll(l3);
            }
            if ((yCount * (xSize - 1) + xCount) >= 0) {
                l4 = (List<Integer>) boxes.get(yCount * (xSize - 1) + xCount).get("contain");
                neiTriOr.addAll(l4);
            }
            if ((yCount * (xSize + 1) + xCount) < boxes.size()) {
                l5 = (List<Integer>) boxes.get(yCount * (xSize + 1) + xCount).get("contain");
                neiTriOr.addAll(l5);
            }
            if ((yCount * (xSize - 1) + xCount - 1) >= 0) {
                l6 = (List<Integer>) boxes.get(yCount * (xSize - 1) + xCount - 1).get("contain");
                neiTriOr.addAll(l6);
            }
            if ((yCount * (xSize - 1) + xCount + 1) >= 0) {
                l7 = (List<Integer>) boxes.get(yCount * (xSize - 1) + xCount + 1).get("contain");
                neiTriOr.addAll(l7);
            }

            if ((yCount * (xSize + 1) + xCount - 1) < boxes.size() && (yCount * (xSize + 1) + xCount - 1) >= 0) {
                l8 = (List<Integer>) boxes.get(yCount * (xSize + 1) + xCount - 1).get("contain");
                neiTriOr.addAll(l8);
            }
            if ((yCount * (xSize + 1) + xCount + 1) < boxes.size()) {
                l9 = (List<Integer>) boxes.get(yCount * (xSize + 1) + xCount + 1).get("contain");
                neiTriOr.addAll(l9);
            }

            List<Integer> neiTri = new ArrayList<>();
            neiTri.addAll(neiTriOr);

            int[] a = element.get(i);
            List<Integer> neighborList = new ArrayList<>();
            strPrintBuilder.append(i + " ");
            for (int j = 0; j < neiTri.size(); j++) {
                if (neiTri.get(j) == i) continue;
                int[] b = element.get(neiTri.get(j));
                Set<Integer> tempsame = tools.getSameElementNew(a, b);
                if (tempsame.size() >= 2) {
                    neighborList.add(neiTri.get(j));
                    strPrintBuilder.append(neiTri.get(j) + " ");

                }

                if (neighborList.size() == 3) {
                    break;
                }

            }
            strPrintBuilder.append("\n");

            neighbor.add(neighborList);
        }

//        箱式索引
        strPrintBuilder.append("******boxes******\n");
//        for (int i = 0; i < boxes.size(); i++) {
//            List<Integer> containbox = (List<Integer>)boxes.get(i).get("contain");
//            if (containbox.size()> 0) {
//                printContent += i + " ";
//                for (int j = 0; j < containbox.size(); j++) {
//                    printContent += containbox.get(j) + " ";
//                }
//                printContent += "\n";
//            }
//        }
        Map<String, Object> returndata = new HashMap<>();
        returndata.put("node", node);
        returndata.put("element", element);
        returndata.put("elementCoordinates", elementCoordinates);
        returndata.put("neighbor", neighbor);
        returndata.put("boxIndex", boxIndex);
        return returndata;
    }

    private void createGeoFile(int tag) throws IOException {
        //tag: 0表示生成 1表示融合
        //        点
        String content = "lc = " + distance + ";\n";
        for (int i = 0; i < borderPoints.size(); i++) {
            double x = borderPoints.get(i).x;
            double y = borderPoints.get(i).y;
            content = content + "Point(" + (i + 1) + ") = {" + x + ", " + y + ", " + 0 + ", " + "lc};\n";
        }
//        线
        for (int i = 1; i <= borderPoints.size(); i++) {

            if (i == borderPoints.size()) {
                content = content + "Line(" + i + ") = {" + i + ", " + 1 + "};\n";
            } else {
                content = content + "Line(" + i + ") = {" + i + ", " + (i + 1) + "};\n";
            }
        }
//        曲线
        content = content + "Curve Loop(1) = {";
        for (int i = 1; i <= borderPoints.size(); i++) {

            if (i == borderPoints.size()) {
                content = content + i + "};\n";
            } else {
                content = content + i + ",";
            }
        }

        content = content + "Plane Surface(1) = {1};\n";
        if (tag == 1) {
            content = content + "Recombine Surface{1};\n";
        }
        File_operation.WriteFile(content, "D:\\gmsh-4.6.0-Windows64\\temp.geo");
    }

    public void create3DGeoFile() throws IOException {
        StringBuilder strContent = new StringBuilder("lcar = " + distance + ";\n");

        strContent.append("x=0;\n");
        strContent.append("y=0;\n");
        strContent.append("z=0;\n");
        strContent.append("r=100;\n");

        strContent.append("Point(1) = {x,  y,  z,  lcar};\n");
        strContent.append("Point(2) = {x+r,y,  z,  lcar};\n");
        strContent.append("Point(3) = {x,  y+r,z,  lcar};\n");
        strContent.append("Point(4) = {x,  y,  z+r,lcar};\n");
        strContent.append("Point(5) = {x-r,y,  z,  lcar};\n");
        strContent.append("Point(6) = {x,  y-r,z,  lcar};\n");
        strContent.append("Point(7) = {x,  y,  z-r,lcar};\n");

        strContent.append("Circle(1) = {2,1,7};\n");
        strContent.append("Circle(2) = {7,1,5};\n");
        strContent.append("Circle(3) = {5,1,4};\n");
        strContent.append("Circle(4) = {4,1,2};\n");
        strContent.append("Circle(5) = {2,1,3};\n");
        strContent.append("Circle(6) = {3,1,5};\n");
        strContent.append("Circle(7) = {5,1,6};\n");
        strContent.append("Circle(8) = {6,1,2};\n");
        strContent.append("Circle(9) = {7,1,3};\n");
        strContent.append("Circle(10) = {3,1,4};\n");
        strContent.append("Circle(11) = {4,1,6};\n");
        strContent.append("Circle(12) = {6,1,7};\n");

        strContent.append("Curve Loop(1) = {5,10,4};\n");
        strContent.append("Curve Loop(2) = {9,-5,1};\n");
        strContent.append("Curve Loop(3) = {12,-8,-1};\n");
        strContent.append("Curve Loop(4) = {8,-4,11};\n");
        strContent.append("Curve Loop(5) = {-10,6,3};\n");
        strContent.append("Curve Loop(6) = {-11,-3,7};\n");
        strContent.append("Curve Loop(7) = {-2,-7,-12};\n");
        strContent.append("Curve Loop(8) = {-6,-9,2};\n");

        strContent.append("Surface(1) = {1};\n");
        strContent.append("Surface(2) = {2};\n");
        strContent.append("Surface(3) = {3};\n");
        strContent.append("Surface(4) = {4};\n");
        strContent.append("Surface(5) = {5};\n");
        strContent.append("Surface(6) = {6};\n");
        strContent.append("Surface(7) = {7};\n");
        strContent.append("Surface(8) = {8};\n");

        strContent.append("Surface Loop(1) = {1, 2, 3, 4, 5, 6, 7, 8};\n");
        strContent.append("Volume(1) = 1;\n");

        File_operation.WriteFile(strContent.toString(), "D:\\gmsh-4.6.0-Windows64\\temp3D.geo");
    }

    public Map creatBacGrid(Double cellLength) {
        Double XMin, YMin, XMax, YMax;
        Double cellsize = cellLength;
        XMin = borderPoints.get(0).x;
        XMax = borderPoints.get(0).x;
        YMin = borderPoints.get(0).y;
        YMax = borderPoints.get(0).y;
        for (Point2D.Double Point : borderPoints) {
            if (Point.x < XMin) XMin = Point.x;
            if (Point.x > XMax) XMax = Point.x;
            if (Point.y < YMin) YMin = Point.y;
            if (Point.y > YMax) YMax = Point.y;
        }


        int xLength = (int) Math.ceil((XMax - XMin) / cellsize);
        int yLength = (int) Math.ceil((YMax - YMin) / cellsize);
//        List<Map> bacGrid = new ArrayList<>(xLength * yLength);
        List<List> boxes = new ArrayList<>();
        for (int i = 0; i < yLength; i++) {
            for (int j = 0; j < xLength; j++) {
//                List<Point2D.Double> coordinates = new ArrayList<>();
//                coordinates.add(new Point2D.Double(XMin + j * cellsize, YMin + i * cellsize));
//                coordinates.add(new Point2D.Double(XMin + (j + 1) * cellsize, YMin + i * cellsize));
//                coordinates.add(new Point2D.Double(XMin + (j + 1) * cellsize, YMin + (i + 1) * cellsize));
//                coordinates.add(new Point2D.Double(XMin + j * cellsize, YMin + (i + 1) * cellsize));
//                Map tempE = new HashMap();
                List<Integer> contain = new ArrayList<>();
//                tempE.put("coordinates", coordinates);
//                tempE.put("contain", contain);
//                bacGrid.add(tempE);
                boxes.add(contain);
            }
        }

        // 存储输出文件
        strPrintBuilder.append("******Basic Information******\n");
        strPrintBuilder.append("startPoint: " + XMin + "  " + YMin + "\n");
        strPrintBuilder.append("xLength: " + xLength + "\n");
        strPrintBuilder.append("yLength: " + yLength + "\n");
        strPrintBuilder.append("precision: " + cellLength + "\n");


        Map returnData = new HashMap();
        returnData.put("boxes", boxes);
        returnData.put("XLength", xLength);
        returnData.put("YLength", yLength);
        returnData.put("precision", cellLength);
        returnData.put("startPoint", new Point2D.Double(XMin, YMin));
        return returnData;

    }

    public Map creatBacGridNew(double cellLength) {
        double XMin, YMin, XMax, YMax;
        double cellsize = cellLength;
        XMin = borderPoints.get(0).x;
        XMax = borderPoints.get(0).x;
        YMin = borderPoints.get(0).y;
        YMax = borderPoints.get(0).y;
        for (Point2D.Double Point : borderPoints) {
            if (Point.x < XMin) XMin = Point.x;
            if (Point.x > XMax) XMax = Point.x;
            if (Point.y < YMin) YMin = Point.y;
            if (Point.y > YMax) YMax = Point.y;
        }


        int xLength = (int) Math.ceil((XMax - XMin) / cellsize);
        int yLength = (int) Math.ceil((YMax - YMin) / cellsize);
        List<Map> bacGrid = new ArrayList<>(xLength * yLength);
        for (int i = 0; i < yLength; i++) {
            for (int j = 0; j < xLength; j++) {
                List<Point2D.Double> coordinates = new ArrayList<>();
                coordinates.add(new Point2D.Double(XMin + j * cellsize, YMin + i * cellsize));
                coordinates.add(new Point2D.Double(XMin + (j + 1) * cellsize, YMin + i * cellsize));
                coordinates.add(new Point2D.Double(XMin + (j + 1) * cellsize, YMin + (i + 1) * cellsize));
                coordinates.add(new Point2D.Double(XMin + j * cellsize, YMin + (i + 1) * cellsize));

                Map tempE = new HashMap();
                List<Integer> contain = new ArrayList<>();
                tempE.put("coordinates", coordinates);
                tempE.put("contain", contain);
                bacGrid.add(tempE);
            }
        }

        Map returnData = new HashMap();

        strPrintBuilder.append("******Basic Information******\n");
        strPrintBuilder.append("startPoint: " + XMin + "  " + YMin + "\n");
        strPrintBuilder.append("xLength: " + xLength + "\n");
        strPrintBuilder.append("yLength: " + yLength + "\n");
        strPrintBuilder.append("precision: " + cellLength + "\n");

        returnData.put("startPoint", new double[]{XMin, YMin});
        returnData.put("xLength", xLength);
        returnData.put("yLength", yLength);
        returnData.put("precision", cellLength);
        returnData.put("boxes", bacGrid);

        return returnData;

    }
}
